<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <style>
        #can{
            display: block;
            margin: 50px auto;
        }
    </style>
    <script src="src/js/webGL/webgl-debug.js"></script>
    <script src="src/js/webGL/webgl-utils.js"></script>
    <script src="src/js/webGL/cuon-utils.js"></script>
    <title>Document</title>

</head>
<body onload="start()">
    <canvas id="can" width="800px" height="800px">
        Your broswer not support
    </canvas>
    <script>
        function start(){
            let canvas = document.getElementById('can')
            let gl = getWebGLContext(canvas)    // 由cuon-utils.js提供
            if(!gl){
                console.log('Failed to get the rendering context for WebGL')
                return
            }
            // 设置着色器代码
            let VSHADER_SOURCE = getVSHADER()
            let FSHADER_SOURCE = getFSHADER()

            // 初始化着色器
            if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){
                console.log('Failed to initialize shaders')
                return
            }
            // 获取attribute变量在顶点着色器中的存储位置 由于gl.program着色器对象属性是在initShaders中创建的，所以需要在它之后调用
            // let a_Position = gl.getAttribLocation(gl.program,'a_Position')
            // if(a_Position < 0){
            //     console.log('Failed to get the storage location of a_Position')
            //     return
            // }
            // let a_PointSize = gl.getAttribLocation(gl.program,'a_PointSize')
            // if(a_PointSize < 0){
            //     console.log('Failed to get the storage location of a_PointSize')
            //     return
            // }
            //将顶点位置传输给attribute变量 ...1f,2f,3f,4f 同族函数
            // gl.vertexAttrib3f(a_Position,0.0,0.0,0.0)
            // gl.vertexAttrib1f(a_PointSize,50.0)

            var n = initVertexBuffers(gl)


            gl.clearColor(0.0,0.0,0.0,1.0)
            gl.clear(gl.COLOR_BUFFER_BIT)

            initTextures(gl,n)
            // gl.drawArrays(gl.POINTS,0,1)
            // gl.drawArrays(gl.TRIANGLES,0,n)
            // console.log('test')
        }// 启动方法

        function initVertexBuffers(gl){
            // var vertices = new Float32Array([0.0,0.5,-0.5,-0.5,0.5,-0.5]) // 点的坐标数组 类型化数组
            var verticesTexCoords = new Float32Array([
                // 顶点坐标 纹理坐标
                -0.5, 0.5, 0.0, 1.0,
                -0.5,-0.5, 0.0, 0.0,
                 0.5, 0.5, 1.0, 1.0,
                 0.5,-0.5, 1.0, 0.0
            ])

            var n = 4   // 定义点的个数

            // var vertexBuffer = gl.createBuffer()    // 创建顶点缓冲区对象   gl.deleteBuffer(buffer) 删除缓冲区对象,buffer是待删除的缓冲区对象
            var vertexTexCoordBuffer = gl.createBuffer()

            gl.bindBuffer(gl.ARRAY_BUFFER,vertexTexCoordBuffer) // 将顶点缓冲区对象绑定到目标对象 目标对象表示缓冲区对象的用途
            gl.bufferData(gl.ARRAY_BUFFER,verticesTexCoords,gl.STATIC_DRAW)  // 向缓冲区对象中写入数据

            var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT

            var a_Position = gl.getAttribLocation(gl.program,'a_Position')  // 获取顶点着色器中为a_Position的attribute变量的地址
            gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,FSIZE * 4,0) // 将缓冲区对象分配给a_Position变量 传递整个缓冲区对象的指针引用
            /*
                gl.vertexAttribPointer(location,size,type,normalized,stride,offset)
                location    指定待分配的attribute变量的存储位置
                size        指定缓冲区中每个顶点的分量个数
                type        指定数据格式    gl.FLOAT/gl.SHORT/gl.INT/gl.UNSIGNED_BYTE
                normalized  传入true/false,表明是否将非浮点型的数据归一化到[0,1],[-1,1]之间
                stride      指定相邻两个顶点之间的字节数，默认为0
                offset      指定缓冲区对象中的偏移量，即attribute变量从何处开始存储(从起始位置开始，offset为0)
            */
            gl.enableVertexAttribArray(a_Position)  // 连接a_Position变量和分配给它的缓冲区变量 开启attribute变量

            var a_TexCoord = gl.getAttribLocation(gl.program,'a_TexCoord')
            gl.vertexAttribPointer(a_TexCoord,2,gl.FLOAT,false,FSIZE * 4,FSIZE * 2)
            gl.enableVertexAttribArray(a_TexCoord)

            return n
        }
        function initTextures(gl,n){
            var texture = gl.createTexture()    // 创建纹理对象 gl.deleteTexture(texture) 删除一个纹理对象

            var u_Sampler = gl.getUniformLocation(gl.program,'u_Sampler')

            var image = new Image()

            image.onload = function(){ loadTexture(gl,n,texture,u_Sampler,image) }

            image.src = 'src/images/texture/flower.jpg'

            return true
        }
        function loadTexture(gl,n,texture,u_Sampler,image){
            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)    // 对纹理对象进行Y轴反转
            gl.activeTexture(gl.TEXTURE0)               // 开启0号纹理单元
            gl.bindTexture(gl.TEXTURE_2D,texture)       // 向目标绑定纹理对象

            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,gl.LINEAR)        // 配置纹理参数 
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)    // 设置水平拉伸(解决使用的图片的分辨率不属于2的幂数这个问题)
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)    // 设置垂直拉伸
            /*
                gl.texParameteri(target,pname,param)
                target  gl.TEXTURE_2D / gl.TEXTURE_CUBE_MAP
                pname   纹理参数                param   参数值(默认值)                  描述
                        gl.TEXTURE_MAG_FILTER           gl.LINEAR                       纹理放大
                        gl.TEXTURE_MIN_FILTER           gl.NEAREST_MIPMAP_LINEAR        纹理缩小
                        gl.TEXTURE_WRAP_S               gl.REPEAT                       纹理水平填充
                        gl.TEXTURE_WRAP_T               gl.REPEAT                       纹理垂直填充

                可以赋值给 gl.TEXTURE_WRAP_S / gl.TEXTURE_WRAP_T 的常量有

                gl.REPEAT           平铺式的重复纹理  
                gl.MIRRORED_REPEAT  镜像对称式的重复纹理
                gl.CLAMP_TO_EDGE    使用纹理图像边缘值
                
            */
            gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image) // 配置纹理图像

            gl.uniform1i(u_Sampler,0)   // 将0号纹理传递给着色器 信息通过取色器u_Sampler进行传递

            gl.clear(gl.COLOR_BUFFER_BIT)

            gl.drawArrays(gl.TRIANGLE_STRIP,0,n) // 绘制矩形
        }
        function getVSHADER(){
            //gl_PointSize = 10.0;\n    该语句只在绘制单个的点的时候才会有效果
            return `
                attribute vec4 a_Position;\n
                attribute vec2 a_TexCoord;\n
                varying vec2 v_TexCoord;\n
                void main(){\n
                    gl_Position = a_Position;\n
                    v_TexCoord = a_TexCoord;\n
                }\n
            `
        }
        function getFSHADER(){
            // gl_FragCoord 该内置变量的第一个和第二个分量分别表示片元在canvas坐标系统中的坐标值
            return `
                precision mediump float;\n

                uniform sampler2D u_Sampler;\n
                varying vec2 v_TexCoord;\n
                void main(){\n
                    gl_FragColor = texture2D(u_Sampler,v_TexCoord);\n
                }\n
            `
        }
    </script>
</body>
</html>